/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.model.disc.parametricintegration;

import java.util.ArrayList;
import java.util.ListIterator;

import br.ufmg.dees.insane.model.disc.integrationpoint.GaussPoint;
import br.ufmg.dees.insane.model.disc.integrationpoint.IntegrationPoint;
import br.ufmg.dees.insane.model.disc.pointforce.PointForce;
import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;

/**
*A class representing the parametric integration for line bulks.<p>
*
*@author Lucas, Marcelo & Pitangueira, Roque
*@version 1.0
*@since Jully 2004
*/

public abstract class Line extends ParametricIntegration
{
	/** Return the integration order of this Equivalent Nodal Load.
	*@return the integration order of this Equivalent Nodal Load.
	*/
	public abstract int getIntegrationOrder();
	
//********************************************************************************
	
	/** Return the ArrayList containing the parametric integration due to line loads.
	*@return pointForces The ArrayList containing many PointForce according the number of nodes. Each PointForce holds one parametric integration.
	*/
	public ArrayList getIntegralF()
	{
		PointForce pf;
		ArrayList<IntegrationPoint> integrationPoints = new ArrayList<IntegrationPoint>();
		ArrayList<PointForce> enl = new ArrayList<PointForce>();
		int nNos = this.getPointForcesList().size();
		double L;
		IVector n;
		IMatrix ftip = new IMatrix(nNos, 6);
		ftip.setZero();
		IMatrix ft = new IMatrix(nNos, 6);
		ft.setZero();
		
		for(int m = 0; m < (this.getIntegrationOrder()); m++)//preenche a lista de pontos de gauss deste metodo 
		{
			IntegrationPoint ip = new GaussPoint();
			ip.setCoord1((this.getIntegrationOrder()-1),m);
			ip.setWeight1((this.getIntegrationOrder()-1),m);
			integrationPoints.add(ip);
		}
		
		ListIterator ips = integrationPoints.listIterator();
		while(ips.hasNext())
		{
			IntegrationPoint ip = (IntegrationPoint) ips.next();
			L = this.getTransformationFactor(ip);
			n = (this.getShape()).getShapeFunction(ip.getCoords());
			for(int i = 0; i < 6; i++) // para todos os graus de liberdade
			{
				IVector tNi = new IVector(nNos);//para um grau de liberdade i, armazena os valores de todos os pointforces
				IVector fti = new IVector(n);//instancia fti, fazendo fti = n
				
				ListIterator pfs = this.getPointForcesList().listIterator();
				int k = 0;
				while(pfs.hasNext())
				{
					pf = (PointForce) pfs.next();
					tNi.setElement(k, ((pf.getForces()).getElement(i)));// percorre a lista de pointforces e coloca na posicao k de tNi a forca correspondente ao grau de liberdade i
					k++;
				}
				double nTNi = n.dot(tNi);//produto escalar n*tNi
				fti.scale(((nTNi)*(ip.getWeights())*(L)));// produto: (fti = n) * nTNi * peso do ponto de gauss * L
				ftip.setColumn(i, fti);//cada coluna de ftip representa a contribuicao do grau de liberdade i de um ponto de gauss
			}

			//cada linha de ft representa um vetor com os seis graus de liberdade possiveis
			ft.add(ftip);//adiciona a contribuicao de cada ponto de gauss
		}
System.out.println("MATRIZ FT: ");
imprimeMatriz(ft);

		
		ListIterator pointfs = this.getPointForcesList().listIterator();
		IVector aux = new IVector(6);
		int b = 0;
		while(pointfs.hasNext())
		{
			pf = (PointForce) pointfs.next();
			PointForce pf1 = new PointForce();
			
			pf1.setCoord(pf.getCoord());
			ft.getRow(b, aux);//atribui a aux os valores da linha b da matrix ft
			for(int a = 0; a < 6; a++)
			{
				pf1.setForce(a, aux.getElement(a));
//				pf.setForce(a, aux.getElement(a));
			}
			aux.zero();
			b++;
			enl.add(pf1);
		}
//		return (this.getPointForcesList());
		return enl;
	}
	
//********************************************************************************
	
	/** Return the ArrayList containing the parametric integration due to line axisymetric loads.
	*@return pointForces The ArrayList containing many PointForce according the number of nodes. Each PointForce holds one parametric integration.
	*/
	public ArrayList getIntegralFTimesX()
	{
		PointForce pf;
		ArrayList<IntegrationPoint> integrationPoints = new ArrayList<IntegrationPoint>();
		ArrayList<PointForce> enl = new ArrayList<PointForce>();
		int nNos = this.getPointForcesList().size();
		double L;
		IVector n;
		IVector vectorX = new IVector(nNos);
		IMatrix ftip = new IMatrix(nNos, 6);
		ftip.setZero();
		IMatrix ft = new IMatrix(nNos, 6);
		ft.setZero();
		
		this.fillVectorX(vectorX);
		for(int m = 0; m < (this.getIntegrationOrder()); m++)//preenche a lista de pontos de gauss deste metodo 
		{
			IntegrationPoint ip = new GaussPoint();
			ip.setCoord1((this.getIntegrationOrder()-1),m);
			ip.setWeight1((this.getIntegrationOrder()-1),m);
			integrationPoints.add(ip);
		}
		
		ListIterator ips = integrationPoints.listIterator();
		while(ips.hasNext())
		{
			IntegrationPoint ip = (IntegrationPoint) ips.next();
			L = this.getTransformationFactor(ip);
			n = (this.getShape()).getShapeFunction(ip.getCoords());
			for(int i = 0; i < 6; i++) // para todos os graus de liberdade
			{
				IVector tNi = new IVector(nNos);//para um grau de liberdade i, armazena os valores de todos os pointforces
				IVector fti = new IVector(n);//instancia fti, fazendo fti = n
				
				ListIterator pfs = this.getPointForcesList().listIterator();
				int k = 0;
				while(pfs.hasNext())
				{
					pf = (PointForce) pfs.next();
					tNi.setElement(k, ((pf.getForces()).getElement(i)));// percorre a lista de pointforces e coloca na posicao k de tNi a forca correspondente ao grau de liberdade i
					k++;
				}
				double nTNi = n.dot(tNi);//produto escalar n*tNi
				double nx = n.dot(vectorX);
				fti.scale(((nTNi)*(ip.getWeights())*(L)*(nx*2*Math.PI)));// produto: (fti = n) * nTNi * peso do ponto de gauss * L * 2*PI * r( r = Ni * xi )
				ftip.setColumn(i, fti);//cada coluna de ftip representa a contribuicao do grau de liberdade i de um ponto de gauss
			}
			//cada linha de ft representa um vetor com os seis graus de liberdade possiveis
			ft.add(ftip);//adiciona a contribuicao de cada ponto de gauss
		}
System.out.println("Matriz ft:");
imprimeMatriz(ft);
		ListIterator pointfs = this.getPointForcesList().listIterator();
		IVector aux = new IVector(6);
		int b = 0;
		while(pointfs.hasNext())
		{
			pf = (PointForce) pointfs.next();
			PointForce pf1 = new PointForce();
			
			pf1.setCoord(pf.getCoord());
/*			PointForce pf1 = new PointForce();
			pf1.setForce(pf.getForces());
			pf1.setCoord(pf.getCoord());
			enl.add(pf1);
*/
			ft.getRow(b, aux);//atribui a aux os valores da linha b da matrix ft
			for(int a = 0; a < 6; a++)
			{
				pf1.setForce(a, aux.getElement(a));
			}
			aux.zero();
			b++;
			enl.add(pf1);
		}
//		return (this.getPointForcesList());
		return enl;
	}
	
//********************************************************************************
	
	/** Return the transformation factor to the natural system and cartesian system.
	*@param ip The IntegrationPoint that will be used for the calculation of transformation factor.
	@return double The transformation factor to the natural system and cartesian system.
	*/
	protected double getTransformationFactor(IntegrationPoint ip)
	{
		PointForce pf;
		double delX, delY, delZ;
		IMatrix aux;
		IVector n = new IVector(this.getPointForcesList().size());
		IVector x = new IVector(this.getPointForcesList().size());
		IVector y = new IVector(this.getPointForcesList().size());
		IVector z = new IVector(this.getPointForcesList().size());
		
		n.zero();
		aux = (this.getShape()).getDerivedShapeFunction(ip.getCoords());
		aux.getRow(0,n);
		ListIterator pfs = this.getPointForcesList().listIterator();
		int i = 0;
		while(pfs.hasNext())
		{
			pf = (PointForce) pfs.next();
			x.setElement(i, ((pf.getCoord()).x));
			y.setElement(i, ((pf.getCoord()).y));
			z.setElement(i, ((pf.getCoord()).z));
			i++;
		}
		delX = (double) n.dot(x);//n x x
		delY = (double) n.dot(y);//n x y
		delZ = (double) n.dot(z);//n x z
		
		return (Math.sqrt((delX*delX)+(delY*delY)+(delZ*delZ)));
	}
	
//********************************************************************************


}
